mod mysql;
mod sqlite;

use model_graph_types::{
    database::DataSource,
    datasource::{
        AttributeCondition, ClassRelationCondition, DataSourceConnector, QueryCondition,
        QueryConditionExpression, QueryExtention, QueryOptions as DataSourceQueryOptions,
        QuerySelect, RelationCondition,
    },
    modeling::{
        system_meta_database, AttributeValueConvertor, BitOperator, Class, ClassGetter,
        ClassPersistence, ClassRelation, ComparsionOperator, DataSourceClassRelationMapping,
        DataSourceClassRelationMappingBuilder, LogicalOperator, MetaConnector, RelationDirection,
        RelationMappingType, RelationRelatedType, Value, ValueOperator, ValueType,
    },
};

use crate::{
    common::SimpleAttributeValueConvertor, connector::SimpleDataSourceConnector,
    modeling_connector::SimpleMetaConnector,
};

pub async fn instance_query(
    ds_connector: &SimpleDataSourceConnector,
    meta_datasource: &Option<DataSource>,
    class_identifier: &String,
    conditions: QueryCondition,
    options: Option<DataSourceQueryOptions>,
) -> anyhow::Result<(String, String, Vec<Value>)> {
    let modeling = SimpleMetaConnector::new_with_meta_datasource(meta_datasource)?;
    let clazz = modeling.get_class(class_identifier).await?;
    //获取映射
    let mapping = modeling.get_class_persistence(class_identifier).await?;

    let (sql, count_sql, args) = genertate_query_data_sql(
        &meta_datasource
            .as_ref()
            .map_or(system_meta_database(), |v| Ok(v.clone()))?,
        &clazz,
        &conditions,
        mapping,
    )
    .await?;

    Ok((sql, count_sql, args))
}

pub async fn attributes_selects(
    ds_connector: &SimpleDataSourceConnector,
    ds_id: u32,
    datasource: &DataSource,
    class: &Class,
    persistence: &ClassPersistence,
    selects: &Vec<QuerySelect>,
    options: Option<DataSourceQueryOptions>,
) -> anyhow::Result<Vec<String>> {
    tracing::debug!("attributes_wheres....");
    let mut select_fields: Vec<String> = vec![];
    //获取映射
    for select_item in selects {
        if let Some(includes) = &select_item.attribute_includes {
            select_fields = includes.clone();
        }
    }
    Ok(select_fields)
}

pub async fn attributes_wheres(
    ds_connector: &SimpleDataSourceConnector,
    datasource: &DataSource,
    class: &Class,
    persistence: &ClassPersistence,
    attributes: &Vec<AttributeCondition>,
    options: Option<DataSourceQueryOptions>,
) -> anyhow::Result<(Vec<String>, Vec<String>, Vec<Value>)> {
    tracing::debug!("attributes_wheres....");
    let mut args = vec![];

    let mut wheres = vec![];

    let attribute_value_convertor = SimpleAttributeValueConvertor::default();
    let class_identifier = &class.identifier;
    //获取映射
    for ac in attributes {
        //获取该属性的类型以及存储类型
        let attribute = class.attribute(&ac.name)?;
        let storage_type = attribute.get_storage_type();
        let name = attribute.get_storage_name();

        let value = attribute_value_convertor
            .get_persistence_value(
                class_identifier,
                &ac.name,
                &Value::String(ac.value.clone()),
                None,
            )
            .await?;

        match ac.operator {
            ComparsionOperator::Equal => {
                wheres.push(format!(" {} = ? ", name));
                args.push(value);
            }
            ComparsionOperator::Contains => {
                wheres.push(format!(" {} = ? ", name));
                args.push(value);
            }
            ComparsionOperator::In => {
                if let Some(values) = &ac.values {
                    //
                    let items = match storage_type {
                        //TODO 特殊字符的替代
                        ValueType::String => values.iter().map(|v| format!("'{}'", v)).collect(),
                        _ => values.clone(),
                    };
                    wheres.push(format!(" {} in( {} ) ", name, items.join(",")));
                }
            }
            _ => {}
        }
    }
    Ok((wheres, vec![], args))
}

pub async fn relations_wheres(
    ds_connector: &SimpleDataSourceConnector,
    ds_id: u32,
    meta_datasource: &DataSource,
    class: &Class,
    persistence: &ClassPersistence,
    relations: &Vec<ClassRelationCondition>,
    options: Option<DataSourceQueryOptions>,
) -> anyhow::Result<(Vec<String>, Vec<String>, Vec<Value>)> {
    let mut wheres = vec![];
    let mut args = vec![];
    let class_identifier = &class.identifier;

    for r in relations {
        //一条关系上的条件
        //获取关系的映射
        if let Ok(relation_mappings) = SimpleMetaConnector::default()
            .class_relations(class_identifier, &r.conditions)
            .await
        {
            if let Some(relation_mapping) = relation_mappings.get(0) {
                match &relation_mapping.related_type {
                    RelationRelatedType::Keys => {
                        //关系属性
                        if class_identifier == &relation_mapping.src_identifier {
                            //正向关系
                            if let Some(class_conditions) = &r.class_conditions {
                                let mut new_conditions = class_conditions.clone();
                                //TODO 联合主键
                                new_conditions.selects = Some(vec![QuerySelect::with_include(
                                    relation_mapping.related_at.clone(),
                                )?]);

                                let (sql, _, mut app_args) = SimpleDataSourceConnector::default()
                                    .instance_query_sql(
                                        &Some(meta_datasource.clone()),
                                        &relation_mapping.target_identifier,
                                        new_conditions,
                                        None,
                                    )
                                    .await?;
                                wheres.push(format!(" {} in ( {} ) ", class.primary_key, sql));
                                args.append(&mut app_args);
                            }
                        } else {
                            //反向关系
                            //关系涉及到的类型条件
                            if let Some(class_conditions) = &r.class_conditions {
                                let mut new_conditions = class_conditions.clone();
                                new_conditions.selects = Some(vec![QuerySelect::with_include(
                                    class.primary_key.clone(),
                                )?]);

                                let (sql, _, mut app_args) = SimpleDataSourceConnector::default()
                                    .instance_query_sql(
                                        &Some(meta_datasource.clone()),
                                        &relation_mapping.src_identifier,
                                        new_conditions,
                                        None,
                                    )
                                    .await?;
                                wheres.push(format!(
                                    " {} in ( {} ) ",
                                    relation_mapping.related_at, sql
                                ));
                                args.append(&mut app_args);
                            }
                        }
                    }
                    RelationRelatedType::Class => {
                        let relation_class_identifier = relation_mapping.related_at.clone();
                        tracing::debug!("======={}", relation_class_identifier);
                        //关系属性
                        if class_identifier == &relation_mapping.src_identifier {
                            //正向关系
                            //关系涉及到的类型条件
                            if let Some(class_conditions) = &r.class_conditions {
                                let mut new_conditions = class_conditions.clone();
                                new_conditions.selects = Some(vec![QuerySelect::with_include(
                                    relation_mapping.related_at.clone(),
                                )?]);

                                let (sql, _, mut app_args) = SimpleDataSourceConnector::default()
                                    .instance_query_sql(
                                        &Some(meta_datasource.clone()),
                                        &relation_mapping.target_identifier,
                                        new_conditions,
                                        None,
                                    )
                                    .await?;
                                wheres.push(format!(
                                    " {} in ( {} ) ",
                                    relation_mapping.related_at, sql
                                ));
                                args.append(&mut app_args);
                            }
                        } else {
                            //反向关系
                            //关系涉及到的类型条件
                        }
                    }
                    _ => {}
                }
            }
            if let Some(attributes) = &r.attributes {}
        //
        } else {
            continue;
        }
    }

    Ok((wheres, vec![], args))
}

pub async fn genertate_query_data_sql(
    meta_datasource: &DataSource,
    clazz: &Class,
    conditions: &QueryCondition,
    mapping: ClassPersistence,
) -> anyhow::Result<(String, String, Vec<Value>)> {
    let mut sql = format!("");
    let mut count_sql = format!("");

    let mut args = vec![];

    let mut wheres = vec![];

    let mut select_str = String::from("*");

    let mut order_str = String::from("");

    let mut limit_str = String::from("");
    //
    let class_identifier = &clazz.identifier;
    let mut table_name = clazz.name.clone();
    //属性条件
    //查询主键
    table_name = mapping.table_name.clone();

    if let Some(attributes) = &conditions.attributes {
        let (mut r, _, mut a) = attributes_wheres(
            &SimpleDataSourceConnector::default(),
            meta_datasource,
            &clazz,
            &mapping,
            attributes,
            None,
        )
        .await?;
        wheres.append(&mut r);
        args.append(&mut a);
    }
    tracing::debug!("{:?}[{:?}]", wheres, args);
    //查询字段
    if let Some(selects) = &conditions.selects {
        let mut select_fields: Vec<String> = vec![];
        for select_item in selects {
            if let Some(includes) = &select_item.attribute_includes {
                select_fields = includes.clone();
            }
        }
        if select_fields.len() > 0 {
            select_str = select_fields.join(",");
        }
    }

    //关系条件
    if let Some(relations) = &conditions.relations {
        let (mut r, mut a) =
            _relation_condition_sql(meta_datasource, class_identifier, relations).await?;
        wheres.append(&mut r);
        args.append(&mut a);
    }

    //表达式
    if let Some(expression) = &conditions.expression {
        let (r, mut a) = _expression_condition_sql(meta_datasource, class_identifier, expression)?;
        wheres.push(r);
        args.append(&mut a);
    }

    //排序条件
    if let Some(orders) = &conditions.orders {}
    //分页条件
    if let Some(page) = &conditions.page {
        let page_size: u32 = if let Some(page_size) = &conditions.page_size {
            *page_size
        } else {
            10
        };
        let offset = (page - 1) * page_size;

        limit_str = format!("limit {},{} ", offset, page_size);
    }

    if wheres.len() > 0 {
        sql = format!(
            "select {} from {} where {} {} {}",
            select_str,
            table_name,
            wheres.join(" and "),
            order_str,
            limit_str
        );
        count_sql = format!(
            "select count(1) from {} where {}",
            table_name,
            wheres.join(" and ")
        );
    } else {
        sql = format!(
            "select {} from {} {} {}",
            select_str, table_name, order_str, limit_str
        );
        count_sql = format!("select count(1) from {}  ", table_name,);
    }

    Ok((sql, count_sql, args))
}

async fn _relation_condition_sql(
    meta_datasource: &DataSource,
    class_identifier: &String,
    relations: &Vec<ClassRelationCondition>,
) -> anyhow::Result<(Vec<String>, Vec<Value>)> {
    let modeling_connector = SimpleMetaConnector::default();

    let mut wheres = vec![];
    let mut args = vec![];
    for r in relations {
        //一条关系上的条件
        //获取关系的映射
        if let Ok(relation_mappings) = SimpleMetaConnector::default()
            .relation_mapping(class_identifier, &r.conditions)
            .await
        {
            if let Some(relation_mapping) = relation_mappings.get(0) {
                let src_class = modeling_connector
                    .get_class(&relation_mapping.src_identifier)
                    .await?;
                let target_class = modeling_connector
                    .get_class(&relation_mapping.target_identifier)
                    .await?;

                let (relation_at_identifier, keys, new_conditions) =
                    match &relation_mapping.mapping_type {
                        RelationMappingType::InnerKeys => {
                            //关系属性
                            if class_identifier == &relation_mapping.src_identifier {
                                //正向关系
                                if let Some(class_conditions) = &r.class_conditions {
                                    let mut new_conditions = class_conditions.clone();
                                    new_conditions.selects = Some(vec![QuerySelect::with_include(
                                        relation_mapping.target_keys.clone(),
                                    )?]);

                                    (
                                        relation_mapping.target_identifier.clone(),
                                        relation_mapping.src_keys.clone(),
                                        new_conditions,
                                    )
                                } else {
                                    let mut new_conditions = QueryCondition::default();
                                    new_conditions.selects = Some(vec![QuerySelect::with_include(
                                        relation_mapping.target_keys.clone(),
                                    )?]);
                                    (
                                        relation_mapping.target_identifier.clone(),
                                        relation_mapping.src_keys.clone(),
                                        new_conditions,
                                    )
                                }
                            } else {
                                //反向关系
                                if let Some(class_conditions) = &r.class_conditions {
                                    let mut new_conditions = class_conditions.clone();
                                    new_conditions.selects = Some(vec![QuerySelect::with_include(
                                        relation_mapping.src_keys.clone(),
                                    )?]);

                                    (
                                        relation_mapping.src_identifier.clone(),
                                        relation_mapping.target_keys.clone(),
                                        new_conditions,
                                    )
                                } else {
                                    let mut new_conditions = QueryCondition::default();
                                    new_conditions.selects = Some(vec![QuerySelect::with_include(
                                        relation_mapping.target_keys.clone(),
                                    )?]);
                                    (
                                        relation_mapping.src_identifier.clone(),
                                        relation_mapping.target_keys.clone(),
                                        new_conditions,
                                    )
                                }
                            }
                        }
                        RelationMappingType::OutterTable => {
                            let relation_class_identifier = relation_mapping.mapping_value.clone();

                            //关系属性
                            if class_identifier == &relation_mapping.src_identifier {
                                //正向关系
                                if let Some(class_conditions) = &r.class_conditions {
                                    let mut new_conditions = class_conditions.clone();
                                    new_conditions.selects = Some(vec![QuerySelect::with_include(
                                        relation_mapping.src_keys.clone(),
                                    )?]);

                                    (
                                        relation_class_identifier,
                                        src_class.primary_key.clone(),
                                        new_conditions,
                                    )
                                } else {
                                    let mut new_conditions = QueryCondition::default();
                                    new_conditions.selects = Some(vec![QuerySelect::with_include(
                                        relation_mapping.target_keys.clone(),
                                    )?]);
                                    (
                                        relation_class_identifier,
                                        src_class.primary_key.clone(),
                                        new_conditions,
                                    )
                                }
                            } else {
                                //反向关系
                                if let Some(class_conditions) = &r.class_conditions {
                                    let mut new_conditions = class_conditions.clone();
                                    new_conditions.selects = Some(vec![QuerySelect::with_include(
                                        relation_mapping.target_keys.clone(),
                                    )?]);
                                    (
                                        relation_class_identifier,
                                        target_class.primary_key.clone(),
                                        new_conditions,
                                    )
                                } else {
                                    let mut new_conditions = QueryCondition::default();
                                    new_conditions.selects = Some(vec![QuerySelect::with_include(
                                        relation_mapping.target_keys.clone(),
                                    )?]);
                                    (
                                        relation_class_identifier,
                                        target_class.primary_key.clone(),
                                        new_conditions,
                                    )
                                }
                            }
                        }
                    };
                let ds_connector = SimpleDataSourceConnector::default();

                let (sql, _, mut app_args) = ds_connector
                    .instance_query_sql(
                        &Some(meta_datasource.clone()),
                        &relation_at_identifier,
                        new_conditions,
                        None,
                    )
                    .await?;
                wheres.push(format!(" {} in ( {} ) ", keys, sql));
                args.append(&mut app_args);
            }
            if let Some(attributes) = &r.attributes {}
        //
        } else {
            continue;
        }
    }

    Ok((wheres, args))
}

fn _expression_condition_sql(
    meta_datasource: &DataSource,
    class_identifier: &String,
    expression: &QueryConditionExpression,
) -> anyhow::Result<(String, Vec<Value>)> {
    let mut wheres = String::new();
    let mut args = vec![];

    //获取关系的映射
    match &expression.operator {
        LogicalOperator::And => {
            wheres.push_str(" ( ");

            if let Some(left_expression) = &expression.left_expression {
                let (left_where, mut left_args) =
                    _expression_condition_sql(meta_datasource, class_identifier, left_expression)?;

                wheres.push_str(left_where.as_str());
                args.append(&mut left_args);
            }
            wheres.push_str(" and ");

            if let Some(right_expression) = &expression.right_expression {
                let (right_where, mut right_args) =
                    _expression_condition_sql(meta_datasource, class_identifier, right_expression)?;
                wheres.push_str(right_where.as_str());
                args.append(&mut right_args);
            }
            wheres.push_str(" ) ");
        }
        LogicalOperator::Or => {
            wheres.push_str(" ( ");

            if let Some(left_expression) = &expression.left_expression {
                let (left_where, mut left_args) =
                    _expression_condition_sql(meta_datasource, class_identifier, left_expression)?;

                wheres.push_str(left_where.as_str());
                args.append(&mut left_args);
            }
            wheres.push_str(" or ");

            if let Some(right_expression) = &expression.right_expression {
                let (right_where, mut right_args) =
                    _expression_condition_sql(meta_datasource, class_identifier, right_expression)?;
                wheres.push_str(right_where.as_str());
                args.append(&mut right_args);
            }
            wheres.push_str(" ) ");
        }
        LogicalOperator::Comparsion(value_operator) => match value_operator {
            ComparsionOperator::Equal => {
                if let Some(left_str) = &expression.left {
                    wheres.push_str(format!("{} = ? ", left_str).as_str());
                    if let Some(value) = &expression.value {
                        args.push(Value::String(value.clone()));
                    }
                }
            }
            _ => {}
        },
        LogicalOperator::BitOperator(bit_operator) => match bit_operator {
            BitOperator::And => {
                if let Some(left_str) = &expression.left {
                    wheres.push_str(format!("{} & ? ", left_str).as_str());
                    if let Some(value) = &expression.value {
                        args.push(Value::Number(
                            value
                                .parse::<i64>()
                                .map_err(|err| anyhow::anyhow!("{}", err))?,
                        ));
                    }
                }
            }
            BitOperator::Or => {}
            _ => {}
        },
    }

    Ok((wheres, args))
}
